package com.hunliji.monitor.manager.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hunliji.common.exception.ErrorException;
import com.hunliji.common.exception.WarnException;
import com.hunliji.monitor.manager.api.FeiShuManager;
import com.hunliji.monitor.manager.api.model.dto.FeiShuSendMsgDTO;
import com.hunliji.monitor.manager.api.model.dto.FeishuUserInfoDTO;
import com.hunliji.monitor.manager.api.model.dto.ObtainAccessTokenDTO;
import com.hunliji.monitor.manager.api.model.dto.ObtainChatGroupDTO;
import com.hunliji.monitor.manager.api.model.dto.ObtainChatGroupMemberDTO;
import com.hunliji.monitor.manager.api.model.param.FeiShuSendMsgManagerParam;
import com.hunliji.monitor.manager.api.model.param.ObtainAccessTokenManagerParam;
import com.hunliji.monitor.manager.config.FeishuProjectConfig;
import com.hunliji.monitor.manager.rest.FeiShuRest;
import com.hunliji.monitor.manager.rest.model.feishu.*;
import com.hunliji.monitor.manager.rest.param.FeiShuObtainAccessTokenRestParam;
import com.hunliji.monitor.manager.rest.param.FeiShuSendMsgRestParam;
import com.hunliji.monitor.manager.rest.param.FeiShuUrgentAppRestParam;
import com.hunliji.monitor.share.component.ComponentLocator;
import com.hunliji.monitor.share.enums.MsgTypeEnum;
import com.hunliji.monitor.share.enums.ReceiveIdTypeEnum;

import java.util.*;

import com.lark.project.core.request.RequestOptions;
import com.lark.project.service.workitem.WorkItemService;
import com.lark.project.service.workitem.builder.CreateWorkItemReq;
import com.lark.project.service.workitem.builder.CreateWorkItemResp;
import com.lark.project.service.workitem.builder.FilterResp;
import com.lark.project.service.workitem.model.WorkItemInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

/**
 * 飞书接口的接入
 * @author wuchen
 */
@Slf4j
@Service
public class FeiShuManagerImpl implements FeiShuManager {
    /**
     * 成功的标记
     */
    private static final Integer SUCCESS_CODE = 0;
    /**
     * 一页默认的大小
     */
    private static final Integer DEFAULT_PAGE_SIZE = 50;
    /**
     * token 前面要拼的前缀
     */
    private static final String TOKEN_PREFIX = "Bearer";

    @Resource
    private FeiShuRest feiShuRest;
    @Resource
    private WorkItemService workItemService;
    @Resource
    private FeishuProjectConfig feishuProjectConfig;



    @Override
    public ObtainAccessTokenDTO obtainToken(ObtainAccessTokenManagerParam obtainAccessTokenManagerParam) {
        FeiShuObtainAccessTokenRestParam feiShuObtainAccessTokenRestParam = ComponentLocator.getConverter().convert(obtainAccessTokenManagerParam, FeiShuObtainAccessTokenRestParam.class);
        FeiShuObtainAccessTokenListRestModel feiShuObtainAccessTokenRestModel = feiShuRest.obtainToken(feiShuObtainAccessTokenRestParam);
        if(SUCCESS_CODE.equals(feiShuObtainAccessTokenRestModel.getCode())){
            ObtainAccessTokenDTO obtainAccessTokenDTO = ComponentLocator.getConverter().convert(feiShuObtainAccessTokenRestModel,ObtainAccessTokenDTO.class);
            return obtainAccessTokenDTO;
        }
        log.warn("obtainToken-获取token发生异常，param:{},obtainAccessTokenRestModel:{}", JSON.toJSONString(feiShuObtainAccessTokenRestParam),JSON.toJSONString(feiShuObtainAccessTokenRestModel));
        throw new WarnException("obtainToken-获取token发生异常");
    }


    /**
     * 用递归的方式获取
     * @param pageToken
     * @param pageSize
     * @param accessToken
     * @return
     */
    private List<ObtainChatGroupDTO> obtainChatGroup(String pageToken,Integer pageSize,String accessToken){
        List<ObtainChatGroupDTO> obtainChatGroupDTOList = new ArrayList<>();
        FeiShuListRestModel<FeiShuObtainChatGroupRestModel> feiShuListRestModel =  feiShuRest.obtainChatGroup(pageToken,pageSize,accessToken);
        //如果本次请求失败，则直接结束处理
        if(!SUCCESS_CODE.equals(feiShuListRestModel.getCode())){
            log.warn("obtainChatGroup-获取飞书群组发生异常，pageToken:{},pageSize:{},accessToken:{},feiShuRestModel:{}",pageToken,pageSize,accessToken,JSON.toJSONString(feiShuListRestModel));
            return obtainChatGroupDTOList;
        }
        //如果无返回数据，则直接结束处理
        if(Objects.isNull(feiShuListRestModel.getData())){
            log.warn("obtainChatGroup-获取飞书群组发生异常，pageToken:{},pageSize:{},accessToken:{},feiShuRestModel:{}",pageToken,pageSize,accessToken,JSON.toJSONString(feiShuListRestModel));
            return obtainChatGroupDTOList;
        }
        FeiShuListDataRestModel<FeiShuObtainChatGroupRestModel> feiShuListDataRestModel = feiShuListRestModel.getData();
        //如果没有数据，则直接返回
        if(CollectionUtils.isEmpty(feiShuListDataRestModel.getItems())){
            return obtainChatGroupDTOList;
        }
        //处理数据
        List<FeiShuObtainChatGroupRestModel> feiShuObtainChatGroupRestModelList = feiShuListDataRestModel.getItems();
        obtainChatGroupDTOList.addAll(ComponentLocator.getConverter().convertList(feiShuObtainChatGroupRestModelList,ObtainChatGroupDTO.class));
        //如果没有更多了，则返回
        if(!feiShuListDataRestModel.getHasMore()){
            return obtainChatGroupDTOList;
        }
        //如果还有更多，则获取
        obtainChatGroupDTOList.addAll(obtainChatGroup(feiShuListDataRestModel.getPageToken(),pageSize,accessToken));
        return obtainChatGroupDTOList;
    }

    @Override
    public List<ObtainChatGroupDTO> obtainChatGroupAll(String accessToken) {
        return obtainChatGroup(null,DEFAULT_PAGE_SIZE,handleToken(accessToken));
    }

    /**
     * 获取的成员id为open_id
     */
    private static final String MEMBER_ID_TYPE_OPEN_ID = "open_id";
    /**
     * 获取群组的成员
     * @param chatGroupId
     * @param pageToken
     * @param pageSize
     * @param accessToken
     * @return
     */
    private List<ObtainChatGroupMemberDTO> obtainChatGroupMember(String chatGroupId, String pageToken, Integer pageSize, String accessToken){
        List<ObtainChatGroupMemberDTO> obtainChatGroupMemberDTOList = new ArrayList<>();
        FeiShuListRestModel<FeiShuObtainChatGroupMemberRestModel> feiShuListRestModel =  feiShuRest.obtainChatGroupMember(chatGroupId,MEMBER_ID_TYPE_OPEN_ID,pageToken,pageSize,accessToken);
        //如果本次请求失败，则直接结束处理
        if(!SUCCESS_CODE.equals(feiShuListRestModel.getCode())){
            log.warn("obtainChatGroupMember-获取飞书群组成员发生异常，chatGroupId:{},pageToken:{},pageSize:{},accessToken:{},feiShuRestModel:{}",chatGroupId,pageToken,pageSize,accessToken,JSON.toJSONString(feiShuListRestModel));
            return obtainChatGroupMemberDTOList;
        }
        //如果无返回数据，则直接结束处理
        if(Objects.isNull(feiShuListRestModel.getData())){
            log.warn("obtainChatGroupMember-获取飞书群组成员发生异常，pageToken:{},pageSize:{},accessToken:{},feiShuRestModel:{}",pageToken,pageSize,accessToken,JSON.toJSONString(feiShuListRestModel));
            return obtainChatGroupMemberDTOList;
        }
        FeiShuListDataRestModel<FeiShuObtainChatGroupMemberRestModel> feiShuListDataRestModel = feiShuListRestModel.getData();
        //如果没有数据，则直接返回
        if(CollectionUtils.isEmpty(feiShuListDataRestModel.getItems())){
            return obtainChatGroupMemberDTOList;
        }
        //处理数据
        List<FeiShuObtainChatGroupMemberRestModel> feiShuObtainChatGroupRestModelList = feiShuListDataRestModel.getItems();
        obtainChatGroupMemberDTOList.addAll(ComponentLocator.getConverter().convertList(feiShuObtainChatGroupRestModelList,ObtainChatGroupMemberDTO.class));
        //如果没有更多了，则返回
        if(!feiShuListDataRestModel.getHasMore()){
            return obtainChatGroupMemberDTOList;
        }
        //如果还有更多，则获取
        obtainChatGroupMemberDTOList.addAll(obtainChatGroupMember(chatGroupId,feiShuListDataRestModel.getPageToken(),pageSize,accessToken));
        return obtainChatGroupMemberDTOList;
    }


    @Override
    public List<ObtainChatGroupMemberDTO> obtainChatGroupMemberAll(String accessToken, String chatGroupId) {
        return obtainChatGroupMember(chatGroupId,null,DEFAULT_PAGE_SIZE,handleToken(accessToken));
    }

    /**
     * 消息类型，富文本
     */
    private static final String MSG_TYPE_POST = "post";
    /**
     * 发送飞书群组消息
     * @param receiveChatId：接收的群ID
     * @param content：接收的消息体
     * @param accessToken:token
     * @return
     */
    @Override
    public FeiShuSendMsgDTO sendChatGroupMsg(String receiveChatId, String content,String accessToken) {
        FeiShuSendMsgRestParam feiShuSendMsgRestParam = new FeiShuSendMsgRestParam();
        feiShuSendMsgRestParam.setReceiveId(receiveChatId);
        feiShuSendMsgRestParam.setMsgType(MsgTypeEnum.POST.getCode());
        feiShuSendMsgRestParam.setContent(content);
        FeiShuRestModel<FeiShuSendMsgRestModel> feiShuRestModel = feiShuRest.sendMsg(
            ReceiveIdTypeEnum.CHAT_ID.getCode(),feiShuSendMsgRestParam,handleToken(accessToken));
        if(SUCCESS_CODE.equals(feiShuRestModel.getCode())){
            FeiShuSendMsgRestModel feiShuSendMsgRestModel = feiShuRestModel.getData();
            if(Objects.isNull(feiShuSendMsgRestModel)){
                log.warn("sendChatGroupMsg-发送群组消息异常,结果项中无数据,feiShuSendMsgRestParam:{},accessToken:{},feiShuRestModel:{}",JSON.toJSONString(feiShuSendMsgRestParam),accessToken,JSON.toJSONString(feiShuRestModel));
                throw new WarnException("发送群组消息异常,结果项中无数据");
            }
            FeiShuSendMsgDTO feiShuSendMsgDTO = ComponentLocator.getConverter().convert(feiShuSendMsgRestModel,FeiShuSendMsgDTO.class);
            return feiShuSendMsgDTO;
        }
        log.warn("sendChatGroupMsg-发送群组消息异常,feiShuSendMsgRestParam:{},accessToken:{},feiShuRestModel:{}",JSON.toJSONString(feiShuSendMsgRestParam),accessToken,JSON.toJSONString(feiShuRestModel));
        throw new WarnException("发送群组消息异常"+feiShuRestModel.getMsg());
    }

    /**
     * 发送消息
     * @param param
     * @param accessToken
     * @return
     */
    @Override
    public FeiShuSendMsgDTO sendMsg(FeiShuSendMsgManagerParam param,String accessToken) {
        FeiShuSendMsgRestParam feiShuSendMsgRestParam = new FeiShuSendMsgRestParam();
        feiShuSendMsgRestParam.setReceiveId(param.getReceiveId());
        feiShuSendMsgRestParam.setMsgType(param.getMsgType());
        feiShuSendMsgRestParam.setContent(param.getContent());
        //log.info("飞书发送消息，参数:{}", JSON.toJSONString(feiShuSendMsgRestParam));
        FeiShuRestModel<FeiShuSendMsgRestModel> feiShuRestModel = feiShuRest.sendMsg(param.getReceiveIdType(),feiShuSendMsgRestParam,handleToken(accessToken));
        if(SUCCESS_CODE.equals(feiShuRestModel.getCode())){
            FeiShuSendMsgRestModel feiShuSendMsgRestModel = feiShuRestModel.getData();
            if(Objects.isNull(feiShuSendMsgRestModel)){
                log.warn("sendChatGroupMsg-发送飞书消息异常,结果项中无数据,feiShuSendMsgRestParam:{},accessToken:{},feiShuRestModel:{}",JSON.toJSONString(feiShuSendMsgRestParam),accessToken,JSON.toJSONString(feiShuRestModel));
                throw new WarnException("发送飞书消息异常,结果项中无数据");
            }
            FeiShuSendMsgDTO feiShuSendMsgDTO = ComponentLocator.getConverter().convert(feiShuSendMsgRestModel,FeiShuSendMsgDTO.class);
            return feiShuSendMsgDTO;
        }
        log.warn("sendChatGroupMsg-发送飞书消息异常,feiShuSendMsgRestParam:{},accessToken:{},feiShuRestModel:{}",JSON.toJSONString(feiShuSendMsgRestParam),accessToken,JSON.toJSONString(feiShuRestModel));
        throw new WarnException("发送飞书消息异常"+feiShuRestModel.getMsg());
    }

    @Override
    public List<String> urgentApp(List<String> userIdList, String messageId,String accessToken) {
        FeiShuUrgentAppRestParam feiShuUrgentAppRestParam = new FeiShuUrgentAppRestParam();
        feiShuUrgentAppRestParam.setUserIdList(userIdList);
        try {
            FeiShuRestModel<FeiShuUrgentAppRestModel> feiShuRestModel = feiShuRest.urgentApp(messageId,feiShuUrgentAppRestParam,"open_id",handleToken(accessToken));
            if(SUCCESS_CODE.equals(feiShuRestModel.getCode())){
                return feiShuRestModel.getData().getInvalidUserIdList();
            }else {
                log.warn("fei shu urgent error,userIdList:{},messageId:{},error info:{}",userIdList,messageId,feiShuRestModel);
                throw new WarnException("飞书应用内加急发生异常");
            }
        }catch (Exception e){
            log.error("fei shu urgent error,userIdList:{},messageId:{}",userIdList,messageId,e);
            throw new ErrorException("飞书应用内加急发生错误");
        }
    }

    @Override
    public List<String> urgentPhone(List<String> userIdList, String messageId, String accessToken) {
        FeiShuUrgentAppRestParam feiShuUrgentAppRestParam = new FeiShuUrgentAppRestParam();
        feiShuUrgentAppRestParam.setUserIdList(userIdList);
        try {
            FeiShuRestModel<FeiShuUrgentAppRestModel> feiShuRestModel = feiShuRest.urgentPhone(messageId,feiShuUrgentAppRestParam,"open_id",handleToken(accessToken));
            if(SUCCESS_CODE.equals(feiShuRestModel.getCode())){
                return feiShuRestModel.getData().getInvalidUserIdList();
            }else {
                log.warn("fei shu urgent error,userIdList:{},messageId:{},error info:{}", userIdList, messageId, feiShuRestModel);
                throw new WarnException("飞书应用内加急发生异常");
            }
        }catch (Exception e){
            log.error("fei shu urgent error,userIdList:{},messageId:{}",userIdList,messageId,e);
            throw new ErrorException("飞书应用内加急发生错误");
        }
    }


    @Override
    public FeishuUserInfoDTO getUserInfo(String userId,String userIdType,String departmentIdType,String accessToken) {
        log.info("飞书发送消息，参数:{} {} {}", userId, userIdType, departmentIdType);
        FeiShuRestModel<FeishuUserInfoResultRestModel> feiShuRestModel = feiShuRest.getUserInfo(userId,
            userIdType, departmentIdType, handleToken(accessToken));
        if (SUCCESS_CODE.equals(feiShuRestModel.getCode())) {
            FeishuUserInfoResultRestModel feiShuRestModelData = feiShuRestModel.getData();
            if (Objects.isNull(feiShuRestModelData)) {
                log.warn(
                    "getUserInfo-获取飞书个人信息异常,结果项中无数据",
                    JSON.toJSONString(feiShuRestModelData), accessToken,
                    JSON.toJSONString(feiShuRestModel));
                throw new WarnException("发送飞书消息异常,结果项中无数据");
            }
            FeishuUserInfoDTO feishuUserInfoDTO = ComponentLocator.getConverter().convert(
                Optional.of(feiShuRestModelData).map(FeishuUserInfoResultRestModel::getUser)
                    .orElse(null), FeishuUserInfoDTO.class);
            return feishuUserInfoDTO;
        }
        log.warn("sendChatGroupMsg-发送飞书消息异常,参数:{} {} {}", userId, userIdType, departmentIdType);
        throw new WarnException("发送飞书消息异常" + feiShuRestModel.getMsg());
    }

    @Override
    public boolean sendRobotMessage(String robotToken, JSONObject param) {
        FeiShuRestModel<JSONObject> result = feiShuRest.sendRobotMessage(robotToken, param);
        return result.getCode() == 0;
    }

    /**====================================== 公共方法区 ============================================**/
    /**
     *  拼装飞书token 格式有一些不一样
     * @param token
     * @return
     */
    private String handleToken(String token){
        return TOKEN_PREFIX + " "+token;
    }

    @Override
    public void createItem(CreateWorkItemReq createWorkItemReq, String accessToken) throws Exception{
        RequestOptions requestOptions = getRequestOption(accessToken, feishuProjectConfig.getUserKey());
        CreateWorkItemResp workItem = workItemService.createWorkItem(createWorkItemReq, requestOptions);
        log.warn("workItem:{}",JSON.toJSONString(workItem));
    }

    private RequestOptions getRequestOption(String accessToken, String userKey) {
        RequestOptions requestOptions = new RequestOptions();
        Map<String, List<String>> headers = new HashMap<>();
        headers.put("X-PLUGIN-TOKEN", Lists.newArrayList(accessToken));
        headers.put("X-USER-KEY", Lists.newArrayList(userKey));
        requestOptions.setHeaders(headers);
        return requestOptions;
    }

    @Override
    public void createItemV2(Map<String, Object> paramMap, String accessToken,String projectKey){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.add("X-PLUGIN-TOKEN",accessToken);
        headers.add("X-USER-KEY",feishuProjectConfig.getUserKey());
        HttpEntity<Map<String, Object>> mapHttpEntity = new HttpEntity<>(paramMap, headers);
        String url = "https://project.feishu.cn/open_api/".concat(projectKey).concat("/work_item/create");
        ResponseData responseData = restTemplate.postForObject(url, mapHttpEntity, ResponseData.class);
        log.warn("response:{}",JSON.toJSONString(responseData));
    }

    @NoArgsConstructor
    @Data
    public static class ResponseData<T>{
        @JsonProperty("err_code")
        private Integer errCode;
        @JsonProperty("err_msg")
        private String errMsg;
        private T data;
        private T err;
    }

}
